<?php
/*******************************************************************************
 *  This file is part of mysql-proxy.
 *
 *  mysql-proxy is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  mysql-proxy is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************
 * Author: Lidanyang  <simonarthur2012@gmail.com>
 ******************************************************************************/


namespace Proxy\Record;


use Proxy\Reporter;

class Redis implements Reporter
{

    const PINT_TICK = 60;  // 60s

    /**
     * @var \Redis
     */
    protected $redis;

    protected $config;

    protected $last_ping;

    /**
     * @param $config       array       配置选项
     * @return bool
     */
    public function init($config)
    {
        $this->config = $config;
        return $this->connect();
    }

    /**
     * @param $key      string
     * @return mixed
     */
    public function exists($key)
    {
        if(!$this->ping())
        {
            return false;
        }
        return $this->redis->exists($key);
    }

    public function set($key, $data, $expire)
    {
        if(!$this->ping())
        {
            return false;
        }
        return $this->redis->setex($key, $expire, $data);
    }

    public function add($key, $rank, $data)
    {
        if(!$this->ping())
        {
            return false;
        }
        return $this->redis->zAdd($key, $rank, $data);
    }

    /**
     * @param $key          string
     * @param $timestamp    int         超时时刻的时间戳
     * @return bool
     */
    public function expireAt($key, $timestamp)
    {
        if(!$this->ping())
        {
            return false;
        }
        return $this->redis->expireAt($key, $timestamp);
    }

    /**
     * @param $key      string
     * @param $expire   int         超时时间，单位秒
     * @return bool
     */
    public function expire($key, $expire)
    {
        if(!$this->ping())
        {
            return false;
        }
        return $this->redis->expire($key, $expire);
    }

    public function hash($key, $hash_key, $data)
    {
        if(!$this->ping())
        {
            return false;
        }
        return $this->redis->hSet($key, $hash_key, $data);
    }

    protected function connect()
    {
        $this->redis = new \Redis();
        if (!$this->redis->connect($this->config['redis_host'], $this->config['redis_port'])) {
            return false;
        }
        if(isset($this->config['redis_auth']))
        {
            if(!$this->redis->auth($this->config['redis_auth']))
            {
                return false;
            }
        }
        if(isset($this->config['redis_select']))
        {
            if(!$this->redis->select($this->config['redis_select']))
            {
                return false;
            }
        }
        $this->last_ping = time();
        return true;
    }

    protected function ping()
    {
        $now = time();
        if($now > ($this->last_ping + self::PINT_TICK))
        {
            try {
                if(!isset($this->redis))
                {
                    $this->connect();
                    return true;
                }
                $this->redis->ping();
                $this->last_ping = $now;
            } catch (\RedisException $e) {
                try {
                    unset($this->redis);
                    return $this->connect();
                } catch (\RedisException $e) {
                    return false;
                }
            }
        }
        return true;
    }



}